package com.ruoyi.business.service.impl;

import java.math.BigDecimal;
import java.util.List;
import java.util.Random;

import com.ruoyi.business.domain.Goods;
import com.ruoyi.business.domain.PurchaseReceiptItem;
import com.ruoyi.business.mapper.GoodsMapper;
import com.ruoyi.business.service.IPurchaseReceiptItemService;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.annotation.DataSource;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.business.mapper.PurchaseReceiptMapper;
import com.ruoyi.business.domain.PurchaseReceipt;
import com.ruoyi.business.service.IPurchaseReceiptService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 进货单Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-03-20
 */
@Service
public class PurchaseReceiptServiceImpl implements IPurchaseReceiptService 
{
    private static final Logger log = LoggerFactory.getLogger(PurchaseReceiptServiceImpl.class);
    
    @Autowired
    private PurchaseReceiptMapper purchaseReceiptMapper;

    @Autowired
    private IPurchaseReceiptItemService purchaseReceiptItemService;
    
    @Autowired
    private GoodsMapper goodsMapper;

    /**
     * 查询进货单
     * 
     * @param id 进货单主键
     * @return 进货单
     */
    @Override
    public PurchaseReceipt selectPurchaseReceiptById(Long id)
    {
        return purchaseReceiptMapper.selectPurchaseReceiptById(id);
    }

    /**
     * 根据单号查询进货单
     * 
     * @param receiptCode 进货单编号
     * @return 进货单
     */
    @Override
    public PurchaseReceipt selectPurchaseReceiptByReceiptCode(String receiptCode)
    {
        PurchaseReceipt purchaseReceipt = purchaseReceiptMapper.selectPurchaseReceiptByReceiptCode(receiptCode);
        if (purchaseReceipt != null) {
            // 查询并设置明细列表
            PurchaseReceiptItem queryItem = new PurchaseReceiptItem();
            queryItem.setReceiptId(purchaseReceipt.getId());
            List<PurchaseReceiptItem> itemList = purchaseReceiptItemService.selectPurchaseReceiptItemList(queryItem);
            purchaseReceipt.setPurchaseReceiptItemList(itemList);
        }
        return purchaseReceipt;
    }

    /**
     * 查询进货单列表
     * 
     * @param purchaseReceipt 进货单
     * @return 进货单
     */
    @DataScope(userAlias="p")
    @Override
    public List<PurchaseReceipt> selectPurchaseReceiptList(PurchaseReceipt purchaseReceipt)
    {
        return purchaseReceiptMapper.selectPurchaseReceiptList(purchaseReceipt);
    }

    /**
     * 新增进货单 - 金蝶风格实现
     * 
     * @param purchaseReceipt 进货单
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertPurchaseReceipt(PurchaseReceipt purchaseReceipt)
    {

        if (purchaseReceipt.getType().equals("paymentOrder")){
            return purchaseReceiptMapper.insertPurchaseReceipt(purchaseReceipt);
        }

        try {
            log.info("开始处理新增进货单请求，供应商ID：{}", purchaseReceipt.getSupplierId());
            
            // 1. 生成进货单号（如果没有）
            if (StringUtils.isEmpty(purchaseReceipt.getReceiptCode())) {
                String dateStr = DateUtils.dateTimeNow("yyyyMMdd");
                String receiptCode = "PR" + dateStr + String.format("%04d", new Random().nextInt(10000));
                purchaseReceipt.setReceiptCode(receiptCode);
                log.info("生成进货单号: {}", receiptCode);
            }
            
            // 2. 设置业务日期（如果没有）
            if (purchaseReceipt.getBusinessDate() == null) {
                purchaseReceipt.setBusinessDate(DateUtils.getNowDate());
            }
            
            // 3. 设置默认状态（待审核）
            if (StringUtils.isEmpty(purchaseReceipt.getStatus())) {
                purchaseReceipt.setStatus("0"); // 0-待审核，1-已审核
            }
            
            // 4. 设置创建时间
            purchaseReceipt.setCreateTime(DateUtils.getNowDate());
            
            // 5. 保存进货单主表
            log.info("开始保存进货单主表: {}", purchaseReceipt.getReceiptCode());
            int rows = purchaseReceiptMapper.insertPurchaseReceipt(purchaseReceipt);
            log.info("进货单主表保存完成, ID: {}", purchaseReceipt.getId());
            
            if (purchaseReceipt.getId() == null) {
                throw new RuntimeException("进货单主表保存失败，未获取到ID");
            }
            
            // 6. 获取明细列表并处理
            List<PurchaseReceiptItem> itemList = purchaseReceipt.getPurchaseReceiptItemList();
            
            // 打印明细项原始数据以便调试
            if (itemList != null && !itemList.isEmpty()) {
                log.info("进货单明细项数量: {}", itemList.size());
                log.info("进货单明细项原始数据:");
                for (int i = 0; i < itemList.size(); i++) {
                    PurchaseReceiptItem item = itemList.get(i);
                    log.info("明细项[{}]: goodsId={}, goodsSpec={}, quantity={}, unitPrice={}",
                            i, item.getGoodsId(), item.getGoodsSpec(),
                            item.getQuantity(), item.getUnitPrice());
                }
                
                // 总金额计算
                BigDecimal totalAmount = BigDecimal.ZERO;
                int itemCount = 0;
                
                for (PurchaseReceiptItem item : itemList) {
                    try {
                        // 检查必要字段
                        if (item.getGoodsId() == null) {
                            log.warn("第{}个明细缺少商品ID，跳过", itemCount + 1);
                            continue;
                        }
                        
                        // 设置进货单ID和编号关联
                        item.setReceiptId(purchaseReceipt.getId());
                        item.setReceiptCode(purchaseReceipt.getReceiptCode());
                        
                        // 设置创建信息
                        item.setCreateBy(purchaseReceipt.getCreateBy());
                        item.setCreateTime(DateUtils.getNowDate());
                        
                        // 计算金额
                        if (item.getQuantity() != null && item.getUnitPrice() != null) {
                            BigDecimal itemAmount = item.getQuantity().multiply(item.getUnitPrice());
                            item.setTotalPrice(itemAmount);
                            totalAmount = totalAmount.add(itemAmount);
                        } else {
                            log.warn("第{}个明细缺少数量或单价信息，设置默认值", itemCount + 1);
                            // 如果为null则设置默认值，防止NPE
                            if (item.getQuantity() == null) {
                                item.setQuantity(BigDecimal.ONE);
                            }
                            if (item.getUnitPrice() == null) {
                                item.setUnitPrice(BigDecimal.ZERO);
                            }
                            item.setTotalPrice(item.getQuantity().multiply(item.getUnitPrice()));
                        }
                        
                        // 补充商品信息
                        if (StringUtils.isEmpty(item.getGoodsName()) || StringUtils.isEmpty(item.getGoodsSpec())) {
                            Goods goods = goodsMapper.selectGoodsById(item.getGoodsId());
                            if (goods != null) {
                                if (StringUtils.isEmpty(item.getGoodsName())) {
                                    item.setGoodsName(goods.getGoodsSpec());
                                }
                                if (StringUtils.isEmpty(item.getGoodsSpec())) {
                                    item.setGoodsSpec(goods.getGoodsSpec());
                                }
                                if (StringUtils.isEmpty(item.getGoodsCode())) {
                                    item.setGoodsCode(goods.getGoodsCode());
                                }
                                if (StringUtils.isEmpty(item.getUnit())) {
                                    item.setUnit(goods.getPrimaryUnit());
                                }
                            }
                        }
                        
                        // 保存明细
                        log.info("保存第{}个明细，商品ID: {}, 商品名称: {}", 
                                itemCount + 1, item.getGoodsId(), item.getGoodsName());
                        int result = purchaseReceiptItemService.insertPurchaseReceiptItem(item);
                        if (result <= 0) {
                            log.error("明细保存失败: {}", item.toString());
                            throw new RuntimeException("明细保存失败，商品ID: " + item.getGoodsId());
                        } else {
                            log.info("明细项[{}]保存成功, ID: {}", itemCount + 1, item.getId());
                        }
                        
                        // 如果单据状态是已审核，则更新库存
                        if ("1".equals(purchaseReceipt.getStatus())) {
                            updateGoodsStock(item);
                        }
                        
                        itemCount++;
                    } catch (Exception e) {
                        log.error("处理明细项时发生错误", e);
                        throw new RuntimeException("处理明细项失败: " + e.getMessage());
                    }
                }
                
                log.info("成功处理{}个明细项", itemCount);
                
                // 更新总金额
                if (purchaseReceipt.getTotalAmount() == null || 
                    purchaseReceipt.getTotalAmount().compareTo(BigDecimal.ZERO) == 0) {
                    purchaseReceipt.setTotalAmount(totalAmount);
                    
                    // 更新主表金额
                    log.info("更新进货单总金额: {}", totalAmount);
                    purchaseReceiptMapper.updatePurchaseReceipt(purchaseReceipt);
                }
            } else {
                log.warn("进货单 [{}] 没有明细项", purchaseReceipt.getReceiptCode());
            }
            
            log.info("进货单 [{}] 保存完成", purchaseReceipt.getReceiptCode());
            return rows;
        } catch (Exception e) {
            log.error("保存进货单失败", e);
            throw new RuntimeException("保存进货单失败: " + e.getMessage(), e);
        }
    }

    /**
     * 修改进货单
     * 
     * @param purchaseReceipt 进货单
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updatePurchaseReceipt(PurchaseReceipt purchaseReceipt)
    {

        if (purchaseReceipt.getType().equals("paymentOrder")){
            return purchaseReceiptMapper.updatePurchaseReceipt(purchaseReceipt);
        }

        try {
            log.info("开始处理修改进货单请求，ID: {}, 单号: {}", 
                    purchaseReceipt.getId(), purchaseReceipt.getReceiptCode());
            
            // 1. 检查进货单ID是否存在
            if (purchaseReceipt.getId() == null) {
                throw new RuntimeException("进货单ID不能为空");
            }
            
            // 2. 查询原进货单信息，用于后续处理和状态对比
            PurchaseReceipt originalReceipt = purchaseReceiptMapper.selectPurchaseReceiptById(purchaseReceipt.getId());
            if (originalReceipt == null) {
                throw new RuntimeException("找不到ID为 " + purchaseReceipt.getId() + " 的进货单");
            }
            
            // 3. 判断状态变化，用于决定是否需要更新库存
            boolean statusChanged = !originalReceipt.getStatus().equals(purchaseReceipt.getStatus());
            boolean becameApproved = statusChanged && "1".equals(purchaseReceipt.getStatus());
            boolean becamePending = statusChanged && "0".equals(purchaseReceipt.getStatus());
            
            // 4. 设置更新时间
            purchaseReceipt.setUpdateTime(DateUtils.getNowDate());
            
            // 5. 更新进货单主表信息
            log.info("更新进货单主表信息: {}", purchaseReceipt.getId());
            int rows = purchaseReceiptMapper.updatePurchaseReceipt(purchaseReceipt);
            if (rows <= 0) {
                throw new RuntimeException("更新进货单主表失败");
            }
            
            // 6. 获取明细列表
            List<PurchaseReceiptItem> itemList = purchaseReceipt.getPurchaseReceiptItemList();
            if (itemList != null && !itemList.isEmpty()) {
                log.info("进货单明细项数量: {}", itemList.size());
                
                // 7. 查询原有明细项
                PurchaseReceiptItem query = new PurchaseReceiptItem();
                query.setReceiptId(purchaseReceipt.getId());
                List<PurchaseReceiptItem> originalItems = purchaseReceiptItemService.selectPurchaseReceiptItemList(query);
                log.info("原进货单明细项数量: {}", originalItems.size());
                
                // 8. 如果从已审核变为未审核，需要回滚库存
                if (becamePending && !originalItems.isEmpty()) {
                    log.info("进货单状态从已审核变为未审核，开始回滚库存");
                    for (PurchaseReceiptItem item : originalItems) {
                        rollbackGoodsStock(item);
                    }
                }
                
                // 9. 删除原有明细项
                if (!originalItems.isEmpty()) {
                    log.info("删除原有明细项");
                    for (PurchaseReceiptItem item : originalItems) {
                        purchaseReceiptItemService.deletePurchaseReceiptItemById(item.getId());
                    }
                }
                
                // 10. 重新插入明细项
                BigDecimal totalAmount = BigDecimal.ZERO;
                int itemCount = 0;
                
                for (PurchaseReceiptItem item : itemList) {
                    try {
                        // 检查必要字段
                        if (item.getGoodsId() == null) {
                            log.warn("第{}个明细缺少商品ID，跳过", itemCount + 1);
                            continue;
                        }
                        
                        // 设置进货单ID和编号关联
                        item.setReceiptId(purchaseReceipt.getId());
                        item.setReceiptCode(purchaseReceipt.getReceiptCode());
                        item.setId(null); // 确保ID为空，以便插入新记录
                        
                        // 设置创建和更新信息
                        if (StringUtils.isEmpty(item.getCreateBy())) {
                            item.setCreateBy(purchaseReceipt.getUpdateBy());
                        }
                        if (item.getCreateTime() == null) {
                            item.setCreateTime(DateUtils.getNowDate());
                        }
                        item.setUpdateBy(purchaseReceipt.getUpdateBy());
                        item.setUpdateTime(DateUtils.getNowDate());
                        
                        // 计算金额
                        if (item.getQuantity() != null && item.getUnitPrice() != null) {
                            BigDecimal itemAmount = item.getQuantity().multiply(item.getUnitPrice());
                            item.setTotalPrice(itemAmount);
                            totalAmount = totalAmount.add(itemAmount);
                        } else {
                            log.warn("第{}个明细缺少数量或单价信息，设置默认值", itemCount + 1);
                            // 如果为null则设置默认值，防止NPE
                            if (item.getQuantity() == null) {
                                item.setQuantity(BigDecimal.ONE);
                            }
                            if (item.getUnitPrice() == null) {
                                item.setUnitPrice(BigDecimal.ZERO);
                            }
                            item.setTotalPrice(item.getQuantity().multiply(item.getUnitPrice()));
                        }
                        
                        // 补充商品信息
                        if (StringUtils.isEmpty(item.getGoodsName()) || StringUtils.isEmpty(item.getGoodsSpec())) {
                            Goods goods = goodsMapper.selectGoodsById(item.getGoodsId());
                            if (goods != null) {
                                if (StringUtils.isEmpty(item.getGoodsName())) {
                                    item.setGoodsName(goods.getGoodsSpec());
                                }
                                if (StringUtils.isEmpty(item.getGoodsSpec())) {
                                    item.setGoodsSpec(goods.getGoodsSpec());
                                }
                                if (StringUtils.isEmpty(item.getGoodsCode())) {
                                    item.setGoodsCode(goods.getGoodsCode());
                                }
                                if (StringUtils.isEmpty(item.getUnit())) {
                                    item.setUnit(goods.getPrimaryUnit());
                                }
                            }
                        }
                        
                        // 保存明细
                        log.info("保存第{}个明细，商品ID: {}, 商品名称: {}", 
                                itemCount + 1, item.getGoodsId(), item.getGoodsName());
                        int result = purchaseReceiptItemService.insertPurchaseReceiptItem(item);
                        if (result <= 0) {
                            log.error("明细保存失败: {}", item.toString());
                            throw new RuntimeException("明细保存失败，商品ID: " + item.getGoodsId());
                        } else {
                            log.info("明细项[{}]保存成功, ID: {}", itemCount + 1, item.getId());
                        }
                        
                        // 如果单据状态是已审核，则更新库存
                        if ("1".equals(purchaseReceipt.getStatus())) {
                            updateGoodsStock(item);
                        }
                        
                        itemCount++;
                    } catch (Exception e) {
                        log.error("处理明细项时发生错误", e);
                        throw new RuntimeException("处理明细项失败: " + e.getMessage());
                    }
                }
                
                log.info("成功处理{}个明细项", itemCount);
                
                // 11. 更新总金额
                if (totalAmount.compareTo(BigDecimal.ZERO) > 0 &&
                    (purchaseReceipt.getTotalAmount() == null || 
                     purchaseReceipt.getTotalAmount().compareTo(BigDecimal.ZERO) == 0)) {
                    purchaseReceipt.setTotalAmount(totalAmount);
                    
                    // 更新主表金额
                    log.info("更新进货单总金额: {}", totalAmount);
                    purchaseReceiptMapper.updatePurchaseReceipt(purchaseReceipt);
                }
            } else {
                log.warn("进货单修改请求没有包含明细项");
            }
            
            log.info("进货单 [{}] 修改完成", purchaseReceipt.getReceiptCode());
            return rows;
        } catch (Exception e) {
            log.error("修改进货单失败", e);
            throw new RuntimeException("修改进货单失败: " + e.getMessage(), e);
        }
    }

    /**
     * 批量删除进货单
     * 
     * @param ids 需要删除的进货单主键
     * @return 结果
     */
    @Override
    public int deletePurchaseReceiptByIds(Long[] ids)
    {
        return purchaseReceiptMapper.deletePurchaseReceiptByIds(ids);
    }

    /**
     * 删除进货单信息
     * 
     * @param id 进货单主键
     * @return 结果
     */
    @Override
    public int deletePurchaseReceiptById(Long id)
    {
        return purchaseReceiptMapper.deletePurchaseReceiptById(id);
    }
    
    /**
     * 更新商品库存 - 进货入库
     * 
     * @param item 进货单明细
     */
    private void updateGoodsStock(PurchaseReceiptItem item) {
        if (item == null || item.getGoodsId() == null || item.getQuantity() == null) {
            return;
        }
        
        try {
            // 1. 查询商品信息
            Goods goods = goodsMapper.selectGoodsById(item.getGoodsId());
            if (goods == null) {
                log.error("找不到商品信息，ID: {}", item.getGoodsId());
                return;
            }
            
            // 2. 计算新库存
            BigDecimal currentStock = goods.getStockQuantity() != null ? 
                    goods.getStockQuantity() : BigDecimal.ZERO;
            BigDecimal newStock = currentStock.add(item.getQuantity());
            goods.setStockQuantity(newStock);
            
            // 3. 更新进货价格
            if (item.getUnitPrice() != null && item.getUnitPrice().compareTo(BigDecimal.ZERO) > 0) {
                goods.setPurchasePrice(item.getUnitPrice());
            }
            
            // 4. 如果是首次入库，设置期初成本
            if (currentStock.compareTo(BigDecimal.ZERO) == 0 && goods.getInitialCost() == null) {
                goods.setInitialCost(item.getUnitPrice());
            }
            
            // 5. 更新商品信息
            goods.setUpdateTime(DateUtils.getNowDate());
            goodsMapper.updateGoods(goods);
            
            log.info("商品 [{}] 库存更新: {} -> {}", goods.getGoodsSpec(), currentStock, newStock);
            
            // 6. 记录库存变动日志
            insertStockLog(item, "进货入库", currentStock, newStock);
            
        } catch (Exception e) {
            log.error("更新库存失败", e);
            throw new RuntimeException("更新库存失败: " + e.getMessage());
        }
    }

    /**
     * 回滚商品库存 - 退货出库
     * 
     * @param item 退货单明细
     */
    private void rollbackGoodsStock(PurchaseReceiptItem item) {
        if (item == null || item.getGoodsId() == null || item.getQuantity() == null) {
            return;
        }
        
        try {
            // 1. 查询商品信息
            Goods goods = goodsMapper.selectGoodsById(item.getGoodsId());
            if (goods == null) {
                log.error("找不到商品信息，ID: {}", item.getGoodsId());
                return;
            }
            
            // 2. 计算新库存
            BigDecimal currentStock = goods.getStockQuantity() != null ? 
                    goods.getStockQuantity() : BigDecimal.ZERO;
            BigDecimal newStock = currentStock.subtract(item.getQuantity());
            goods.setStockQuantity(newStock);
            
            // 3. 更新商品信息
            goods.setUpdateTime(DateUtils.getNowDate());
            goodsMapper.updateGoods(goods);
            
            log.info("商品 [{}] 库存更新: {} -> {}", goods.getGoodsSpec(), currentStock, newStock);
            
            // 4. 记录库存变动日志
            insertStockLog(item, "退货出库", currentStock, newStock);
            
        } catch (Exception e) {
            log.error("回滚库存失败", e);
            throw new RuntimeException("回滚库存失败: " + e.getMessage());
        }
    }
    
    /**
     * 记录库存变动日志
     * 
     * @param item 操作相关明细
     * @param operationType 操作类型（进货入库/退货出库等）
     * @param beforeQuantity 操作前数量
     * @param afterQuantity 操作后数量
     */
    private void insertStockLog(PurchaseReceiptItem item, String operationType, 
                               BigDecimal beforeQuantity, BigDecimal afterQuantity) {
        try {
            // 构建库存日志对象
            // 如果系统中已有StockLog实体类，使用该类；否则这里只做日志记录
            
            // 记录库存变动的关键信息
            String logMessage = String.format(
                "库存变动日志 - 操作类型: %s, 单据编号: %s, 商品ID: %s, 商品名称: %s, " +
                "变动数量: %s, 变动前: %s, 变动后: %s, 操作人: %s, 操作时间: %s",
                operationType,
                item.getReceiptCode(),
                item.getGoodsId(),
                item.getGoodsName(),
                item.getQuantity(),
                beforeQuantity,
                afterQuantity,
                item.getUpdateBy(),
                DateUtils.getTime()
            );
            
            log.info(logMessage);
            
            // TODO: 如果需要将库存变动记录持久化到数据库，可以在此处实现
            // StockLog stockLog = new StockLog();
            // stockLog.setGoodsId(item.getGoodsId());
            // stockLog.setGoodsName(item.getGoodsName());
            // stockLog.setOperationType(operationType);
            // stockLog.setBeforeQuantity(beforeQuantity);
            // stockLog.setAfterQuantity(afterQuantity);
            // stockLog.setChangeQuantity(item.getQuantity());
            // stockLog.setDocumentCode(item.getReceiptCode());
            // stockLog.setDocumentType("进货单");
            // stockLog.setCreateBy(item.getUpdateBy());
            // stockLog.setCreateTime(DateUtils.getNowDate());
            // stockLogMapper.insertStockLog(stockLog);
            
        } catch (Exception e) {
            // 记录日志出错不应影响主流程，所以只记录错误但不抛出异常
            log.error("记录库存变动日志失败", e);
        }
    }
}
